using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;

namespace Trentacular.SharePoint.Features.Util
{
	/// <summary>
	/// Summary description for Util.
	/// </summary>
	public static class StringUtils
    {
        public static bool NullSafeEquals(string str1, string str2)
        {
            return NullSafeEquals(str1, str2, StringComparison.InvariantCulture);
        }

        public static bool NullSafeEquals(string str1, string str2, StringComparison comparisonType)
        {
            if (str1 == null && str2 == null)
                return true;

            if (str1 == null || str2 == null)
                return false;

            return str1.Equals(str2, comparisonType);
        }

		public static string Delimit(ICollection input, string startDelimiter, string endDelimiter)
		{
			StringBuilder sb = new StringBuilder();
			foreach(object s in input)
			{
				sb.Append(startDelimiter).Append(s.ToString()).Append(endDelimiter);
			}
			return sb.ToString();
		}

		public static string Delimit(IEnumerable input, string delimiter)
		{
			StringBuilder sb = new StringBuilder();

			foreach (object o in input)
			{
				sb.Append(o==null? "" : o.ToString());
				sb.Append(delimiter);
			}

			if (sb.Length > 0) {
				sb.Remove(sb.Length - delimiter.Length, delimiter.Length);
			}

			return sb.ToString();
		}

        public static string ReplaceStrings(string template, IDictionary values, string formatString)
        {
            for (IDictionaryEnumerator iter = values.GetEnumerator(); iter.MoveNext(); )
            {
                string key = iter.Key.ToString();
                if (formatString != null)
                    key = string.Format(formatString, key);
                string value = null;
                if (iter.Value != null)
                    value = iter.Value.ToString();
                template = template.Replace(key, value);
            }
            return template;
        }


        /// <summary>
        /// Simple template population using IDictionary for keys.
        /// Looks for exact match to Key in template string and replaces with Value.
        /// </summary>
		public static string ReplaceStrings (string template, IDictionary values)
		{			
			return ReplaceStrings(template,values,null);
		}

        public static string Replace(string input, Regex regex, Converter<Match, string> converter)
        {

            Match match = regex.Match(input);
            if (match.Success)
            {
                StringBuilder sb = new StringBuilder();
                int startIndex = 0;
                while (match.Success)
                {
                    if (match.Index != startIndex)
                        sb.Append(input, startIndex, match.Index - startIndex);
                    startIndex = match.Index + match.Length;
                    // do replace                    
                    sb.Append(converter(match));
                    if (startIndex < input.Length)
                    {
                        sb.Append(input, startIndex, input.Length - startIndex);
                    }
                    match = match.NextMatch();
                }
                return sb.ToString();
            }
            return input;

        }

        public static string ConvertHtmlToPlainText(string html)
        {
            // First remove linebreaks and tabs
            string result = html.Replace("\r", " ").Replace("\n", " ").Replace("\t", " ");
            
            // Add "real linebreaks" before and after Ps and DIVs
            //result = Regex.Replace(result, @"(<p[^>]*>|</p[^>]*>|<br>|<br\s*/>)", "<br/>", "\n");
            

            // strip out javascript
            result = Regex.Replace(result, @"<script[^>]*?>.*?</script>", string.Empty, RegexOptions.IgnoreCase);

            // strip out all tags
            result = Regex.Replace(result, @"<[^>]*>", string.Empty, RegexOptions.IgnoreCase);
            // result = Regex.Replace(result, @"<[\/\!]*?[^<>]*?>", string.Empty, RegexOptions.IgnoreCase);

            // replace special characters
            result = Regex.Replace(result, @"&bull;", " * ", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&lsaquo;", "<", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&rsaquo;", ">", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&(rsquo|lsquo);", "'", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&(quot|ldquo|rdquo);", "\"", RegexOptions.IgnoreCase);            
            result = Regex.Replace(result, @"&trade;", "(tm)", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&frasl;", "/", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&(quot|#34|#034|#x22);", "\"", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&(amp|#38|#038|#x26);", "&", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&(lt|#60|#060|#x3c);", "<", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&(gt|#62|#062|#x3e);", ">", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&(copy|#169);", "(c)", RegexOptions.IgnoreCase);
            result = Regex.Replace(result, @"&(reg|#174);", "(r)", RegexOptions.IgnoreCase);

            // Remove all others. More can be added, see
            // http://hotwired.lycos.com/webmonkey/reference/special_characters/
            result = Regex.Replace(result, @"&(.{2,6});", string.Empty, RegexOptions.IgnoreCase);

            // Remove repeating spaces
            result = Regex.Replace(result, @"( )+", " ");
            
            return result;
        }

        /// <summary>
        /// this function strips non-numeric values out of a string and returns the numeric content of a string
        /// http://coercedcode.blogspot.com/2008/02/c.html
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static string StripNonNumeric(string value)
        {
            return Regex.Replace(value, "\\D", "");
        }

        public static string TruncateText(string text, int characters, bool avoidWordBreak, bool addEllipsis)
        {
            if (string.IsNullOrEmpty(text))
                return string.Empty;

            int stringSize = characters;

            if (text.Length <= stringSize)
                return text;

            if (addEllipsis)
                stringSize -= 3;
                        
            stringSize = Math.Max(0, Math.Min(text.Length, stringSize));

            text = text.Substring(0, stringSize);

            if (avoidWordBreak)
            {
                int lastSpaceIndex = text.LastIndexOf(" ");
                if (lastSpaceIndex > 0 && characters - lastSpaceIndex < 10)
                    text = text.Substring(0, text.LastIndexOf(" "));
            }
            
            if (addEllipsis)
                text += "...";

            return text;
        }
	}
}
